// -----------------------------
// Author: 		Dhaenens Gert 
// Creation: 	12/29/2013 9:34:59 PM				
// -----------------------------

#ifndef _Matrix_h
#define _Matrix_h

#include "Defines.h"
#include "Vector2.h"
#include "Vector3.h"
#include "Vector4.h"

struct Matrix
{

	/* Datamembers */
	Vector4		x;
	Vector4		y;
	Vector4		z;
	Vector4		t;

	/* Constructors */
	Matrix();
	Matrix(Vector4 x, Vector4 y, Vector4 z, Vector4 t);
	Matrix(Vector4 t);
	Matrix(Float arr[16]);

	Matrix(const Matrix& refMatrix);

	Matrix& operator=(const Matrix& refMatrix);

	/* Comparison Operators */
	Bool operator==(const Matrix& refMatrix) const;
	Bool operator!=(const Matrix& refMatrix) const;
	Bool operator<(const Matrix& refMatrix) const;
	Bool operator>(const Matrix& refMatrix) const;
	Bool operator<=(const Matrix& refMatrix) const;
	Bool operator>=(const Matrix& refMatrix) const;

	/* Math In-Place Operators */
	Matrix& operator*=(const Matrix& refMatrix);
	Matrix& operator/=(const Matrix& refMatrix);

	/* Math Out-Of-Place Operators */
	Matrix operator*(const Matrix& refMatrix) const;
	Matrix operator/(const Matrix& refMatrix) const;

	/* Math Friend Operators */
	friend Vector4 operator*(const Vector4& refVector, const Matrix& refMatrix);
	friend Vector4 operator/(const Vector4& refVector, const Matrix& refMatrix);

	/* Methods */
	Vector4	Transform(const Vector4& refVector) const;
	Matrix	Transform(const Matrix& refMatrix) const;
	Vector4	Untransform(const Vector4& refVector) const;
	Matrix	Untransform(const Matrix& refMatrix) const;
	Matrix	Inverse() const;
	Float	Minor(UInt32 i) const;
	Float	CoFactor(UInt32 i) const;
	Matrix	CoFactorMatrix() const;
	Matrix	Transpose() const;
	Matrix	Adjugate() const;
	Float	Determinant() const;
	void	AsArray(Float arr[16]) const;

	/* Static Methods */
	static Matrix	LookAt(const Vector4& vPosition, const Vector3& vDirection, const Vector3& vUp);
	static Matrix	Perspective(Float fFov, Float fAspectRatio, Float fNear, Float fFar);
	static Matrix	RotationX(Float fAngle);
	static Matrix	RotationY(Float fAngle);
	static Matrix	RotationZ(Float fAngle);
	static Matrix	RotationXYZ(Float fAngleX, Float fAngleY, Float fAngleZ);
	static Matrix	RotateAround(Float fAngle, const Vector3& vAxis);
	static Matrix	RotateAround(Float fAngle, const Vector3& vAxis, const Vector4& vOrigin);
	static Matrix	Translation(const Vector4& vPosition);
	static Matrix	Translation(const Vector3& vPosition);
	static Matrix	Scale(Float fScaleX, Float fScaleY, Float fScaleZ);

};

#endif